package pl.com.sthaether.mc.components.treetable.filterable;

import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.transformation.FilteredList;
import javafx.event.EventHandler;
import javafx.scene.control.*;
import javafx.scene.control.cell.TextFieldTreeTableCell;
import javafx.scene.layout.VBox;
import javafx.util.converter.NumberStringConverter;
import pl.com.sthaether.mc.config.MCCurrentState;
import pl.com.sthaether.mc.engine.data.MCMapDataObject;
import pl.com.sthaether.mc.main.toolbar.MCToolbar;

import java.util.ArrayList;
import java.util.List;

public class MCFilterableTreeTable extends VBox { //TODO
    private TextField searchField;
    private TreeTableView<MCFilterableTreeTableNode> table;


    public MCFilterableTreeTable(List<TreeItem<MCFilterableTreeTableNode>> itemsList) {
        init();
        setTableData(itemsList);
    }

    public MCFilterableTreeTable() {
        init();
        setTableData(new ArrayList<>());
    }

    private void init() {
        searchField = new TextField();
        table = createTreeTable();
        table.prefHeightProperty().bind(heightProperty());
        this.getChildren().addAll(searchField, table);
    }

    public void setTableData(List<TreeItem<MCFilterableTreeTableNode>> itemsList) {
        FilteredList<TreeItem<MCFilterableTreeTableNode>> filteredData = new FilteredList<>(FXCollections.observableList(itemsList), t -> true);
        TreeItem<MCFilterableTreeTableNode> rootNode = new TreeItem<>();
        rootNode.setExpanded(true);
        rootNode.getChildren().setAll(filteredData);
        searchField.textProperty().addListener((observable, oldValue, newValue) -> {
            filteredData.setPredicate(row -> {
                if (newValue == null || newValue.isEmpty()) {
                    return true;
                }
                return row.getValue().matchesText(newValue);
            });
            rootNode.getChildren().setAll(filteredData);
        });
        table.setRoot(rootNode);


    }


    private TreeTableView<MCFilterableTreeTableNode> createTreeTable() {
        TreeTableView<MCFilterableTreeTableNode> table = new TreeTableView<>();
        table.setShowRoot(false);
        TreeItem<MCFilterableTreeTableNode> rootNode = new TreeItem<>();
        rootNode.setExpanded(true);
        table.setRoot(rootNode);


        TreeTableColumn<MCFilterableTreeTableNode, String> columnName = new TreeTableColumn<>("Name");
        columnName.setMinWidth(150);
        columnName.setCellValueFactory(cellData -> cellData.getValue().getValue().nameProperty());
        columnName.setCellFactory(TextFieldTreeTableCell.forTreeTableColumn());
        table.getColumns().add(columnName);

        TreeTableColumn<MCFilterableTreeTableNode, Number> columnProperty = new TreeTableColumn<>("Property");
        columnProperty.setMinWidth(100);
        columnProperty.setCellValueFactory(cellData -> cellData.getValue().getValue().nodeValueProperty());
        columnProperty.setCellFactory(TextFieldTreeTableCell.<MCFilterableTreeTableNode, Number>forTreeTableColumn(new NumberStringConverter()));
//        columnProperty.setOnEditCommit(val -> MCCurrentState.getInstance().getCurrentMap().getData().autoColorByValues());
        columnProperty.setOnEditCommit(event -> {
//            MCCurrentState.getInstance().getCurrentMap().getData().getObjectsMap().get(table.getSelectionModel().getSelectedItem().getParent().getParent().getValue().nameProperty().getValue()).updateChart();

            table.getSelectionModel().getSelectedItem().getValue().nodeValueProperty().setValue(event.getNewValue());
            for(MCMapDataObject o : MCCurrentState.getInstance().getCurrentMap().getData().getObjectsMap().values()){
                o.updateChart();//TODO performance problem
            }
            MCCurrentState.getInstance().getCurrentMap().getData().autoColorByValues();
        });
//        columnProperty.setOnEditStart(new EventHandler<TreeTableColumn.CellEditEvent<MCFilterableTreeTableNode, Number>>() {//TODO - to complete
//            @Override
//            public void handle(TreeTableColumn.CellEditEvent<MCFilterableTreeTableNode, Number> event) {
//                if (event.getOldValue() == null) {
//                    return;
//                }
//            }
//        });
        columnName.setOnEditCommit(new EventHandler<TreeTableColumn.CellEditEvent<MCFilterableTreeTableNode, String>>() {
            @Override
            public void handle(TreeTableColumn.CellEditEvent<MCFilterableTreeTableNode, String> event) {
                final TreeItem<MCFilterableTreeTableNode> selectedItem = table.getSelectionModel().getSelectedItem().getParent();
                String name = event.getNewValue();//table.getSelectionModel().getSelectedItem().getValue().nameProperty().getValue();
                if (name != null && !name.equals("")) {
                    if (!name.equals("Add")) {
                        final TreeItem<MCFilterableTreeTableNode> newItem =
                                new TreeItem<>(new MCFilterableTreeTableNode(new SimpleStringProperty("Add"), null));
                        selectedItem.getChildren().add(newItem);

                        final int rowIndex = table.getRow(newItem);
                        table.getSelectionModel().getSelectedItem().getValue().nameProperty().setValue(name);
//                        table.edit(rowIndex, columnName);//Does 99% not start or get canceled, why?
                    }
                } else if (selectedItem.getChildren().size() > 1 && !event.getOldValue().equals("Add")) {
                    selectedItem.getChildren().remove(table.getSelectionModel().getSelectedItem());
                } else {
                    table.getSelectionModel().getSelectedItem().getValue().nameProperty().setValue("Add");
                }

            }
        });


        table.getColumns().add(columnProperty);
        columnProperty.setEditable(true);
        columnProperty.onEditStartProperty();


        table.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
        table.getSelectionModel().setCellSelectionEnabled(true);
        table.setEditable(true);

        return table;
    }

    public void updateData() {
        //tODO !
        List<TreeItem<MCFilterableTreeTableNode>> nodesList = new ArrayList<>();
        for (MCMapDataObject obj : MCCurrentState.getInstance().getCurrentMap().getData().getObjectsMap().values()) {
            nodesList.add(MCFilterableTreeTableNode.generateMapObjectTree(obj));
        }
        MCToolbar.getInstance().getTable().setTableData(nodesList);
    }
}